import 'dart:async';
import 'dart:developer';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:zootix/constants/zt_constants.dart';
import 'package:zootix/services/zt_service.dart';
import 'package:zootix/services/zt_translate.service.dart';
import 'package:zootix/store/zt_auth.store.dart';
import 'package:zootix/util/zt_common.util.dart';
import 'package:zootix/util/zt_logger_util.dart';
import 'package:zootix/zt_config.dart';

/// 打点请求头key统一传参
class ZtLogHeadersKey {
  static const String ztData = "data";
  static const String ztLogType = "log_type";
  static const String ztSubtype = "subtype";
  static const String ztBehavior = "behavior";
  static const String ztDeviceId = "device-id";
  static const String ztAndroidId = "android_id";
  static const String ztuserId = "user_id";
  static const String ztPkg = "pkg";
  static const String ztChnId = "chn_id";
  static const String ztVer = "ver";
  static const String ztPlatform = "platform";
  static const String ztModel = "model";
  static const String ztPVer = "p_ver";
  static const String ztLanId = "lan_id";
  static const String ztSecId = "sec_id";
  static const String ztUtmSource = "utm_source";
  static const String ztAfAdgroupId = "af_adgroup_id";
  static const String ztAfAdset = "af_adset";
  static const String ztAfAdsetId = "af_adset_id";
  static const String ztAfStatus = "af_status";
  static const String ztAfAgency = "af_agency";
  static const String ztAfChannel = "af_channel";
  static const String ztAfCampaign = "campaign";
  static const String ztAfCampaignId = "campaign_id";
  static const String ztCountry = "country";
  static const String ztsysLan = "sys_lan";
}

/// 打点中所有涉及到的页面KEY
class ZtLogPages {
  static const String onboarding = '/launch';
  static const String fastLogin = '/quicklogin';
  static const String terms = '/terms';
  static const String privacy = '/privacy';
  static const String loginsuccess = '/loginsuccess';
  static const String applelogin = '/applelogin';
  static const String purchase = '/purchase';
  static const String createorder = '/createorder';
  static const String logout = '/logout';
  static const String editavatar = '/editavatar';
  static const String deleteaccount = '/deleteaccount';
  static const String customer = '/customer';
  static const String report = '/report';
  static const String block = '/block';
}

/// 打点类型
enum ZtLogType {
  globalBehavior('event', 'global_behavior', 'event'),
  clickEvent("event", "click", "event");

  final String logType;
  final String subType;
  final String behavior;

  const ZtLogType(this.logType, this.subType, this.behavior);
}

// 打点管理
class ZtLogManger {
  static final ZtLogManger _instance = ZtLogManger._internal();
  factory ZtLogManger() {
    return _instance;
  }
  ZtLogManger._internal();

  static const String tag = "ZtLogManger"; // 日志标签
  static const int limitSize = 20; // 打点任务最多缓存长度
  static int _serialId = 0;
  static String launcherId = ZtCommonUtil.generateMd5(
      '${DateTime.now().millisecondsSinceEpoch}${ZtStorageService.to.getString(ZtCacheKeys.deviceUUID, isWithUser: false) ?? ''}');
  final List<Map<String, dynamic>> cacheList = [];
  bool _isWaitingForSend = false; // 是否需要延迟上报
  static const String _event = 'event';
  static const String _tm = 'tm';
  static const String _page = 'page';
  static const String _subPage = 'sub_page';
  static const String _terPage = 'test_pge';
  static const String _userId = 'user_id';
  static const String _duration = 'duration';
  static const String _logType = 'log_type';
  static const String _pkg = 'pkg';
  static const String _ver = 'ver';
  static const String _model = 'model';
  static const String _platform = 'platform';
  static const String _pVer = 'p_ver';
  static const String _lanId = 'lan_id';
  static const String _sysLan = 'sys_lan';
  static const String _country = 'country';
  static const String _behavior = 'behavior';
  static const String _deviceId = 'device-id';
  static Map<String, dynamic> buildEvent(
      {String? page,
      String? subPage,
      String? terPage,
      String? userId,
      ZtLogType? logType}) {
    var map = <String, dynamic>{};

    if (logType != null) {
      map[_logType] = logType.logType;
      map[_behavior] = logType.behavior;
    }

    if (Platform.isAndroid) {
      map[_platform] = 'Android';
      map[_model] = ZtAppInfoService.to.androidDeviceInfo?.hardware ?? '';
    } else if (Platform.isIOS) {
      map[_platform] = 'iOS';
      map[_model] = ZtAppInfoService.to.iosDeviceInfo?.model ?? '';
    }
    map[_deviceId] = ZtStorageService.to
            .getString(ZtCacheKeys.deviceUUID, isWithUser: false) ??
        '';
    map[_userId] = ZtAuthStore.to.userInfo.value.userId;
    map[_pkg] = ZtStorageService.to
        .getString(ZtCacheKeys.packageName, isWithUser: false);
    map[_ver] =
        ZtStorageService.to.getString(ZtCacheKeys.ver, isWithUser: false);
    map[_pVer] =
        ZtStorageService.to.getString(ZtCacheKeys.pVer, isWithUser: false) ??
            '';
    map[_sysLan] = ZtTranslateService.to.languageCode.value;
    map[_country] = ZtAuthStore.to.userInfo.value.country;
    map[_lanId] = launcherId;
    map[ZtLogHeadersKey.ztSecId] = _serialId;
    if (page != null) {
      map[_page] = page;
    }
    if (subPage != null) {
      map[_subPage] = subPage;
    }
    if (terPage != null) {
      map[_terPage] = terPage;
    }
    if (userId != null) {
      map[_userId] = userId;
    }
    map[_duration] = 0;
    map[_event] = 'pv';
    map[_tm] = DateTime.now().millisecondsSinceEpoch;
    if (kDebugMode) {
      log('$map', name: 'LogPvMgr');
    }
    return map;
  }

  /// 上报日志
  void putLog(ZtLogType logType, Map<String, dynamic>? event) {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = _buildItemData(
        logType.logType, logType.subType, logType.behavior, event);
    cacheList.insert(0, itemData);
    sendDelayed();
  }

  /// 延时发送日志
  void sendDelayed() {
    if (_isWaitingForSend) {
      return;
    }
    _isWaitingForSend = true;
    Timer(const Duration(milliseconds: 2000), () {
      _isWaitingForSend = false;
      sendLog(false);
    });
  }

  /// 发日志打点
  void sendLog(bool forceUploadAll) {
    try {
      List<Map<String, dynamic>> sendList = [];
      if (cacheList.isEmpty) {
        return;
      } else if (cacheList.length >= limitSize && !forceUploadAll) {
        sendList.addAll(cacheList.sublist(0, limitSize));
        cacheList.removeRange(0, limitSize);
      } else {
        sendList.addAll(cacheList);
        cacheList.clear();
      }
      _doUpload(sendList, true);
    } catch (e) {
      if (kDebugMode) {
        print(e);
      }
    }
  }

  /// 立马发送日志
  void putLogRightNow(ZtLogType logType, Map<String, dynamic>? event) {
    if (logType.logType.isEmpty ||
        logType.subType.isEmpty ||
        logType.behavior.isEmpty ||
        event == null ||
        event.isEmpty) {
      return;
    }
    Map<String, dynamic> itemData = _buildItemData(
        logType.logType, logType.subType, logType.behavior, event);
    List<Map<String, dynamic>> list = [];
    list.add(itemData);

    _doUpload(list, false);
  }

  /// 执行上传
  Future<void> _doUpload(
      List<Map<String, dynamic>> sendList, bool isContinue) async {
    final dio = Dio(BaseOptions(
      baseUrl: ZtGloablConfig.TRACKING_URL,
      connectTimeout: const Duration(seconds: 10),
    ));
    Map<String, String> data = {};
    try {
      final response = await dio.post(ZtUrls.trackingLog, data: sendList);
      if (isContinue) {
        sendDelayed();
      }
    } catch (e) {
      ZtLoggerUtil().error('[Util Tracking log] $e');
    }
  }

  Map<String, dynamic> _buildItemData(String logType, String subType,
      String behavior, Map<String, dynamic>? event) {
    String platform = '';
    String model = '';
    if (Platform.isAndroid) {
      platform = 'Android';
      model = ZtAppInfoService.to.androidDeviceInfo?.hardware ?? '';
    } else if (Platform.isIOS) {
      platform = 'iOS';
      model = ZtAppInfoService.to.iosDeviceInfo?.model ?? '';
    }
    Map<String, dynamic> itemData = {};
    itemData[ZtLogHeadersKey.ztData] = [event];
    itemData[ZtLogHeadersKey.ztLogType] = logType;
    itemData[ZtLogHeadersKey.ztSubtype] = subType;
    itemData[ZtLogHeadersKey.ztBehavior] = behavior;
    itemData[ZtLogHeadersKey.ztDeviceId] = ZtStorageService.to
            .getString(ZtCacheKeys.deviceUUID, isWithUser: false) ??
        '';
    itemData[ZtLogHeadersKey.ztuserId] = ZtAuthStore.to.userInfo.value.userId;
    itemData[ZtLogHeadersKey.ztPkg] = ZtStorageService.to
        .getString(ZtCacheKeys.packageName, isWithUser: false);
    itemData[ZtLogHeadersKey.ztChnId] = '';
    itemData[ZtLogHeadersKey.ztVer] =
        ZtStorageService.to.getString(ZtCacheKeys.ver, isWithUser: false);
    itemData[ZtLogHeadersKey.ztPlatform] = platform;
    itemData[ZtLogHeadersKey.ztModel] = model;
    itemData[ZtLogHeadersKey.ztPVer] =
        ZtStorageService.to.getString(ZtCacheKeys.pVer, isWithUser: false) ??
            '';
    itemData[ZtLogHeadersKey.ztLanId] = launcherId;
    itemData[ZtLogHeadersKey.ztSecId] = _serialId++;
    itemData[ZtLogHeadersKey.ztsysLan] =
        ZtTranslateService.to.languageCode.value;
    itemData[ZtLogHeadersKey.ztCountry] = ZtAuthStore.to.userInfo.value.country;
    return itemData;
  }
}
